﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Module.SiteWidgets.Interfaces;
using umbraco;
using System.Xml;
using Core.Module.Interfaces.Model;
using System.Configuration;
using System.IO;
using System.Reflection;
using System.Web.UI;
using Core.Module;
using umbraco.NodeFactory;
using umbraco.presentation.templateControls;
using umbraco.presentation;
using System.Web.UI.HtmlControls;
using Core.Module.Interfaces.Controller;
using Core.Module.Interfaces;
using Module.MultiSiteFields.Interfaces;
using Module.MultiSiteFields.Controls.DynamicTreePicker;
using Module.DefaultContent.Interfaces;
using Core.Module.Common;
using umbraco.BusinessLogic;

namespace Module.SiteWidgets
{
    public class SiteWidgetsModule : ISiteWidjetsModule
    {
        #region main properties
        public string Id
        {
            get { return "1DF82D7E-B7B5-4822-85C4-AE103C60044E"; }
        }
        public string Alias
        {
            get { return "SiteWidgetsModule"; }
        }
        public string Title
        {
            get { return ui.Text("multisite", "Module_" + Alias); }
        }
        public bool Enabled { get; set; }
        public bool Active { get; set; }
        [System.ComponentModel.DefaultValue(3)]
        public int Position { get; set; }
        public XmlElement Settings { get; set; }
        public ISite Site { get; set; }
        public IDefaultContentModule Defaults { get; set; }
        public IModuleNode Widgets { get; set; }
        private INodeController<IFrontend> NodeController { get; set; }
        #endregion

        private string FilePath
        {
            get
            {
                return string.Concat(new object[] { GlobalSettings.FullpathToRoot, Path.DirectorySeparatorChar, "web.config" });
            }
        }


        public void Init(ISite site)
        {
            NodeController = ObjectManager.Resolve<INodeController<IFrontend>>();

            ConnectToDefaultModule();
            AllAliases = umbraco.cms.businesslogic.macro.Macro.GetAll().Select(mi => mi.Alias).ToList();
            WrongSettings = CheckWidgetDocumetTypesSettings();

            if (site.Settings != null) Widgets = NodeController.GetPropertyAsNode(site.Settings, "widgetsId");
            if (Widgets == null && site.Settings != null) Widgets = NodeController.GetChild(site.Settings.Id, "Widgets");
            if (Widgets != null)
            {
                IStartPointsController spoints = ObjectManager.Resolve<IStartPointsController>();
                spoints.Register("content", "Site.Widgets", (sp, node) =>
                {
                    if (!EnsureSite(node)) return false;
                    spoints.SetValue(sp, "StartFrom", Widgets.Id);
                    return true;
                });
            }
        }

        private List<string> CheckWidgetDocumetTypesSettings()
        {
            List<string> result = new List<string>();            
            foreach (XmlElement bnode in Settings.SelectNodes("banner"))
            {
                string bAlias = bnode.GetAttribute("name");
                string bMacros = bnode.GetAttribute("macroAlias");
                if (!AllAliases.Contains(bMacros))
                {
                    result.Add(bMacros);
                }
            }
            return result;
        }

        public IEnumerable<Control> GetPageWidgets(IModuleNode forPage, string fromProperty)
        {
            if (!EnsureSite(forPage)) return null;
            DynamicTreeValue v = GetSelectedNodes(forPage, fromProperty);
            List<Control> result = new List<Control>();
            if (v == null || v.Nodes == null)
            {
                result.Add(new LiteralControl("<!-- no page banners in column:" + fromProperty + "-->"));
            }
            else
            {
                foreach (var inode in v.Nodes)
                {
                    IModuleNode bnode = NodeController.Get(inode.id);
                    if (bnode == null)
                    {
                        result.Add(new LiteralControl("<!-- Wrong banner col:[" + fromProperty + "], id:[" + inode.id ?? "" + "]-->"));
                        continue;
                    };
                    Macro banner = new Macro();
                    string macroAlias = ExtractMacroInfo(banner, bnode);
                    if (!AllAliases.Contains(macroAlias) || !string.IsNullOrEmpty(WrongSettings.Where(si => macroAlias.Equals(si, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault()))
                    {
                        string message = string.Format("Wrong banner settings, page id:[{0}],property:'{1}', macros with alias:{2} doesn't exist!", inode.id, fromProperty, macroAlias);
                        Log.Add(LogTypes.Notify, int.Parse(inode.id), message);
                        result.Add(new LiteralControl(string.Concat("<!--", message, "-->\r\n")));
                    }
                    else
                    {
                        banner.Alias = macroAlias;
                        banner.Attributes.Add("macroAlias", macroAlias);
                        banner.Attributes.Add("macroPage", inode.id);
                        banner.Attributes.Add("currentPage", forPage.Id);

                        result.Add(CreateEditingContainer(banner,bnode));
                    }
                }
            }
            return result;
        }

        private DynamicTreeValue GetSelectedNodes(IModuleNode forPage, string fromProperty)
        {
            string pagedata = NodeController.GetPropertyValue(forPage, fromProperty) as string;
            if (string.IsNullOrEmpty(pagedata)) return GetPageDefaults(forPage, fromProperty);
            DynamicTreeValue result = pagedata.FromXml<DynamicTreeValue>();
            if (result == null || result.Nodes == null) return GetPageDefaults(forPage, fromProperty);
            return result;
        }
        private DynamicTreeValue GetPageDefaults(IModuleNode forPage, string fromProperty)
        {
            if (Defaults == null) return null;
            IModuleNode defnode = Defaults.GetDefault(forPage);
            if (defnode == null) return null;
            string pagedata = NodeController.GetPropertyValue(defnode, fromProperty) as string;
            if (string.IsNullOrEmpty(pagedata)) return null;
            return pagedata.FromXml<DynamicTreeValue>();
        }


        #region internal methods

        private bool EnsureSite(IModuleNode forPage)
        {
            return Site.Node.Id.Equals(forPage.SiteId);//throw new exception ???
        }

        private void ConnectToDefaultModule()
        {
            Defaults = Context.Frontend.Modules.Get(Site, "DefaultContentModule") as IDefaultContentModule;

        }


        private string ExtractMacroInfo(Macro banner, IModuleNode bannerNode)
        {
            string resAlias = NodeController.GetPropertyValue(bannerNode, "macroAlias") as string;
            if (string.IsNullOrEmpty(resAlias) && Settings != null)
            {
                XmlNode n = Settings.SelectSingleNode("banner[@name='" + bannerNode.Alias + "']/@macroAlias");
                if (n == null || string.IsNullOrEmpty(n.Value))                
                    resAlias=bannerNode.Alias;//maybe exist macros with same name?
                else if (n != null && !string.IsNullOrEmpty(n.Value))
                    resAlias=n.Value;//alias in the config, check it
                if (!string.IsNullOrEmpty(resAlias))
                {
                    string res=AllAliases.Where(ai => ai.Equals(bannerNode.Alias, StringComparison.InvariantCultureIgnoreCase)).FirstOrDefault();
                    if (!string.IsNullOrEmpty(res)) return res;
                }
                return  "widget-data-default-renderer";
            };
            return resAlias;
        }

        private Control CreateEditingContainer(Macro banner,IModuleNode bannerNode)
        {
            if (UmbracoContext.Current.LiveEditingContext.Enabled)
            {
                HtmlGenericControl editingContainer = new HtmlGenericControl();
                editingContainer.TagName = "div";
                editingContainer.Attributes.Add("class", "banner_edit");

                HtmlGenericControl edit = new HtmlGenericControl();
                edit.TagName = "div";
                edit.InnerText = "edit";
                edit.Attributes.Add("class", "edt_button");
                edit.Attributes.Add("onclick", string.Format("javascript:showEditNodeDialog('{0}','Edit Widget Settings {1}');", banner.Attributes["macroPage"], bannerNode==null?"":":" +bannerNode.Name));

                editingContainer.Controls.Add(edit);
                editingContainer.Controls.Add(banner);
                return editingContainer;
            }
            return banner;
        }
        #region  widgets registration

        ///// <summary>
        ///// todo:   1 - default banner alias by banner nodetype        
        ///// </summary>
        //private void RegisterMacroses()
        //{

        //    XmlDocument xDoc = UmbracoContext.Current.GetXml();
        //    XmlElement currentPage = xDoc.GetElementById(SourcePageId.ToString());
        //    if (currentPage != null)
        //    {
        //        XmlNodeList banners = currentPage.SelectNodes(this.SourceFieldName + "/*/*/link/data");

        //        //get default banners
        //        if (banners.Count == 0)
        //        {
        //            banners = currentPage.SelectNodes(string.Format("./ancestor::*[@isDoc and name() = 'Site']/settings/*[name() = 'pageDefaults']/*[name() = '{0}']/{1}/*/*/link/data", currentPage.Name, SourceFieldName));
        //            // banners = xDoc.SelectNodes(string.Format("//Site[@isDoc]/settings/*[name() = 'pageDefaults']/*[name() = '{0}']/{1}/*/*/link/data", currentPage.Name, SourceFieldName));
        //        }
        //        if (banners.Count == 0)
        //            this.Controls.Add(new LiteralControl("<!-- no banners for column:" + this.SourceFieldName + "-->"));
        //        else
        //        {
        //            foreach (XmlNode item in banners)
        //            {
        //                Node m = new Node(int.Parse(item.InnerText));
        //                if (m.Id > -1)
        //                {
        //                    Macro banner = new Macro();
        //                    string macroAlias = ExtractMacroInfo(banner, m);

        //                    banner.Alias = macroAlias;
        //                    banner.Attributes.Add("macroAlias", macroAlias);
        //                    banner.Attributes.Add("macroPage", m.Id.ToString());
        //                    banner.Attributes.Add("currentPage", currentPage.Attributes["id"].Value);

        //                    this.Controls.Add(CreateEditingContainer(banner));
        //                }
        //                else this.Controls.Add(new LiteralControl("<!-- Wrong banner col:[" + this.SourceFieldName + "], id:[" + item.InnerText ?? "" + "]-->"));
        //            }
        //        }
        //    }
        //}

        //public static void RenderSimpleBanner(string id, HtmlTextWriter writer)
        //{
        //    Int32 bannerPageId = 0;
        //    if (!Int32.TryParse(id, out bannerPageId) || bannerPageId < 0)
        //        writer.WriteLine("<!-- wrong banner id:" + id + ",cant cast it to int32,can't render simple banner");
        //    else
        //    {
        //        Node m = new Node(bannerPageId);
        //        Macro banner = new Macro();
        //        string macroAlias = ExtractMacroInfo(banner, m);

        //        banner.Alias = macroAlias;
        //        banner.Attributes.Add("macroAlias", macroAlias);
        //        banner.Attributes.Add("macroPage", m.Id.ToString());
        //        banner.Attributes.Add("currentPage", (UmbracoContext.Current.PageId ?? -1).ToString());
        //        banner.RenderControl(writer);
        //    };
        //}

        //private static string ExtractMacroInfo(Macro banner, Node m)
        //{
        //    Property alias = m.Properties.OfType<Property>().SingleOrDefault(p => p.Alias == "macroAlias");
        //    string resAlias = alias == null || string.IsNullOrEmpty(alias.Value) ? "" : alias.Value;
        //    if (string.IsNullOrEmpty(resAlias) && DefaultAliases != null)
        //    {
        //        XmlNode n = DefaultAliases.SelectSingleNode("banner[@name='" + m.NodeTypeAlias + "']/@macroAlias");
        //        resAlias = n == null || string.IsNullOrEmpty(n.Value) ? "bannerTitleIDL" : n.Value;
        //    }
        //    return resAlias;
        //}

        //private static XmlNode bannersSettings;
        //public static XmlNode DefaultAliases
        //{
        //    get
        //    {
        //        if (bannersSettings == null) bannersSettings = UmbracoSettings.GetKeyAsNode("ism/defaults/banners");
        //        return bannersSettings;
        //    }
        //}

        //private Control CreateEditingContainer(Macro banner)
        //{
        //    if (UmbracoContext.Current.LiveEditingContext.Enabled)
        //    {
        //        HtmlGenericControl editingContainer = new HtmlGenericControl();
        //        editingContainer.TagName = "div";
        //        editingContainer.Attributes.Add("class", "banner_edit");

        //        HtmlGenericControl edit = new HtmlGenericControl();
        //        edit.TagName = "div";
        //        edit.InnerText = "edit";
        //        edit.Attributes.Add("class", "edt_button");
        //        edit.Attributes.Add("onclick", string.Format("javascript:showEditNodeDialog('{0}');", banner.Attributes["macroPage"]));

        //        editingContainer.Controls.Add(edit);
        //        editingContainer.Controls.Add(banner);
        //        return editingContainer;
        //    }

        //    return banner;
        //}

        #endregion

        #endregion



        public List<string> WrongSettings { get; set; }
        public List<string> AllAliases{get;set;}
        
    }
}
